﻿using Caliburn.Micro;
using Microsoft.Win32;
using SD.Common;
using SD.Infrastructure.DTOBase;
using SD.Infrastructure.WPF.Caliburn.Aspects;
using SD.Infrastructure.WPF.Caliburn.Base;
using SD.Infrastructure.WPF.Extensions;
using SD.Infrastructure.WPF.Interfaces;
using SD.Infrastructure.WPF.Models;
using SD.IOC.Core.Mediators;
using SD.Toolkits.Excel;
using SlamDunk.MES.Client.ViewModels.Facility;
using SlamDunk.MES.IAppService.DTOs.Outputs.MaintenanceContext;
using SlamDunk.MES.IAppService.DTOs.Outputs.ResourceContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.MES.Presentation;
using SlamDunk.MES.Presentation.Maps;
using SlamDunk.MES.Presentation.Models.ExportModels;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel.Extensions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace SlamDunk.MES.Client.ViewModels.EquipmentAsset
{
    /// <summary>
    /// 设备资产首页视图模型
    /// </summary>
    public class IndexViewModel : ScreenBase, IPaginatable
    {
        #region # 字段及构造器

        /// <summary>
        /// 资源定义服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IResourceContract> _resourceContract;

        /// <summary>
        /// 维护管理服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IMaintenanceContract> _maintenanceContract;

        /// <summary>
        /// 窗口管理器
        /// </summary>
        private readonly IWindowManager _windowManager;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        public IndexViewModel(ServiceProxy<IResourceContract> resourceContract, ServiceProxy<IMaintenanceContract> maintenanceContract, IWindowManager windowManager)
        {
            this._resourceContract = resourceContract;
            this._maintenanceContract = maintenanceContract;
            this._windowManager = windowManager;

            //默认值
            this.PageIndex = 1;
            this.PageSize = 20;
        }

        #endregion

        #region # 属性

        #region 关键字 —— string Keywords
        /// <summary>
        /// 关键字
        /// </summary>
        [DependencyProperty]
        public string Keywords { get; set; }
        #endregion

        #region 页码 —— int PageIndex
        /// <summary>
        /// 页码
        /// </summary>
        [DependencyProperty]
        public int PageIndex { get; set; }
        #endregion

        #region 页容量 —— int PageSize
        /// <summary>
        /// 页容量
        /// </summary>
        [DependencyProperty]
        public int PageSize { get; set; }
        #endregion

        #region 总记录数 —— int RowCount
        /// <summary>
        /// 总记录数
        /// </summary>
        [DependencyProperty]
        public int RowCount { get; set; }
        #endregion

        #region 总页数 —— int PageCount
        /// <summary>
        /// 总页数
        /// </summary>
        [DependencyProperty]
        public int PageCount { get; set; }
        #endregion

        #region 已选设备 —— EquipmentInfo SelectedEquipment
        /// <summary>
        /// 已选设备
        /// </summary>
        [DependencyProperty]
        public EquipmentInfo SelectedEquipment { get; set; }
        #endregion

        #region 已选设备状态 —— EquipmentStatus? SelectedEquipmentStatus
        /// <summary>
        /// 已选设备状态
        /// </summary>
        [DependencyProperty]
        public EquipmentStatus? SelectedEquipmentStatus { get; set; }
        #endregion

        #region 已选工厂模型 —— Node SelectedFacility
        /// <summary>
        /// 已选工厂模型
        /// </summary>
        [DependencyProperty]
        public Node SelectedFacility { get; set; }
        #endregion

        #region 设备资产列表 —— ObservableCollection<Wrap<EquipmentAssetInfo>> EquipmentAssets
        /// <summary>
        /// 设备资产列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<Wrap<EquipmentAssetInfo>> EquipmentAssets { get; set; }
        #endregion

        #region 设备列表 —— ObservableCollection<EquipmentInfo> Equipments
        /// <summary>
        /// 设备列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<EquipmentInfo> Equipments { get; set; }
        #endregion

        #region 设备状态字典 —— IDictionary<string, string> EquipmentStatuses
        /// <summary>
        /// 设备状态字典
        /// </summary>
        [DependencyProperty]
        public IDictionary<string, string> EquipmentStatuses { get; set; }
        #endregion

        #endregion

        #region # 方法

        //Initializations

        #region 初始化 —— override async Task OnInitializeAsync(CancellationToken cancellationToken)
        /// <summary>
        /// 初始化
        /// </summary>
        protected override async Task OnInitializeAsync(CancellationToken cancellationToken)
        {
            IEnumerable<EquipmentInfo> equipments = await Task.Run(() => this._resourceContract.Channel.GetEquipmentsByPage(null, null, null, 1, int.MaxValue).Datas, cancellationToken);
            this.Equipments = new ObservableCollection<EquipmentInfo>(equipments);

            this.EquipmentStatuses = typeof(EquipmentStatus).GetEnumMembers();

            await this.ReloadEquipmentAssets();
        }
        #endregion


        //Actions

        #region 选择工厂模型 —— async void SelectFacility()
        /// <summary>
        /// 选择工厂模型
        /// </summary>
        public async void SelectFacility()
        {
            this.Busy();

            SelectFacilityViewModel viewModel = ResolveMediator.Resolve<SelectFacilityViewModel>();
            bool? result = await this._windowManager.ShowDialogAsync(viewModel);
            if (result == true)
            {
                this.SelectedFacility = viewModel.SelectedFacility;
            }

            this.Idle();
        }
        #endregion

        #region 清空工厂模型 —— async void ClearFacility()
        /// <summary>
        /// 清空工厂模型
        /// </summary>
        public async void ClearFacility()
        {
            this.SelectedFacility = null;
        }
        #endregion

        #region 加载设备资产列表 —— async void LoadEquipmentAssets()
        /// <summary>
        /// 加载设备资产列表
        /// </summary>
        public async void LoadEquipmentAssets()
        {
            await this.ReloadEquipmentAssets();
        }
        #endregion

        #region 创建设备资产 —— async void CreateEquipmentAsset()
        /// <summary>
        /// 创建设备资产
        /// </summary>
        public async void CreateEquipmentAsset()
        {
            AddViewModel viewModel = ResolveMediator.Resolve<AddViewModel>();
            viewModel.Load(this.Equipments);
            bool? result = await this._windowManager.ShowDialogAsync(viewModel);
            if (result == true)
            {
                await this.ReloadEquipmentAssets();
            }
        }
        #endregion

        #region 修改设备资产 —— async void UpdateEquipmentAsset()
        /// <summary>
        /// 修改设备资产
        /// </summary>
        public async void UpdateEquipmentAsset()
        {
            #region # 验证

            if (this.EquipmentAssets.Count(x => x.IsChecked == true) != 1)
            {
                MessageBox.Show("请勾选一条要修改的设备资产！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            Wrap<EquipmentAssetInfo> equipmentAsset = this.EquipmentAssets.Single(x => x.IsChecked == true);

            this.Busy();

            UpdateViewModel viewModel = ResolveMediator.Resolve<UpdateViewModel>();
            viewModel.Load(equipmentAsset.Model);
            bool? result = await this._windowManager.ShowDialogAsync(viewModel);

            this.Idle();

            if (result == true)
            {
                await this.ReloadEquipmentAssets();
            }
        }
        #endregion

        #region 删除设备资产 —— async void RemoveEquipmentAssets()
        /// <summary>
        /// 删除设备资产
        /// </summary>
        public async void RemoveEquipmentAssets()
        {
            #region # 加载勾选

            EquipmentAssetInfo[] checkedEquipmentAssets = this.EquipmentAssets.Where(x => x.IsChecked == true).Select(x => x.Model).ToArray();
            if (!checkedEquipmentAssets.Any())
            {
                MessageBox.Show("请勾选要删除的设备资产！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            MessageBoxResult result = MessageBox.Show("确定要删除吗？", "警告", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            if (result == MessageBoxResult.Yes)
            {
                this.Busy();

                IMaintenanceContract maintenanceContract = this._maintenanceContract.Channel;
                await Task.Run(() => checkedEquipmentAssets.ForEach(authority => maintenanceContract.RemoveEquipmentAsset(authority.Id)));
                await this.ReloadEquipmentAssets();

                this.Idle();
            }
        }
        #endregion

        #region 正常设备资产 —— async void NormalizeEquipmentAssets()
        /// <summary>
        /// 正常设备资产
        /// </summary>
        public async void NormalizeEquipmentAssets()
        {
            #region # 加载勾选

            EquipmentAssetInfo[] checkedEquipmentAssets = this.EquipmentAssets.Where(x => x.IsChecked == true).Select(x => x.Model).ToArray();
            if (!checkedEquipmentAssets.Any())
            {
                MessageBox.Show("请勾选要正常的设备资产！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            MessageBoxResult result = MessageBox.Show("确定要正常吗？", "警告", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            if (result == MessageBoxResult.Yes)
            {
                this.Busy();

                IMaintenanceContract maintenanceContract = this._maintenanceContract.Channel;
                await Task.Run(() => checkedEquipmentAssets.ForEach(authority => maintenanceContract.NormalizeEquipmentAsset(authority.Id)));
                await this.ReloadEquipmentAssets();

                this.Idle();
            }
        }
        #endregion

        #region 故障设备资产 —— async void FailEquipmentAssets()
        /// <summary>
        /// 故障设备资产
        /// </summary>
        public async void FailEquipmentAssets()
        {
            #region # 加载勾选

            EquipmentAssetInfo[] checkedEquipmentAssets = this.EquipmentAssets.Where(x => x.IsChecked == true).Select(x => x.Model).ToArray();
            if (!checkedEquipmentAssets.Any())
            {
                MessageBox.Show("请勾选要故障的设备资产！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            MessageBoxResult result = MessageBox.Show("确定要故障吗？", "警告", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            if (result == MessageBoxResult.Yes)
            {
                this.Busy();

                IMaintenanceContract maintenanceContract = this._maintenanceContract.Channel;
                await Task.Run(() => checkedEquipmentAssets.ForEach(authority => maintenanceContract.FailEquipmentAsset(authority.Id)));
                await this.ReloadEquipmentAssets();

                this.Idle();
            }
        }
        #endregion

        #region 维护设备资产 —— async void MaintainEquipmentAssets()
        /// <summary>
        /// 维护设备资产
        /// </summary>
        public async void MaintainEquipmentAssets()
        {
            #region # 加载勾选

            EquipmentAssetInfo[] checkedEquipmentAssets = this.EquipmentAssets.Where(x => x.IsChecked == true).Select(x => x.Model).ToArray();
            if (!checkedEquipmentAssets.Any())
            {
                MessageBox.Show("请勾选要维护的设备资产！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            MessageBoxResult result = MessageBox.Show("确定要维护吗？", "警告", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            if (result == MessageBoxResult.Yes)
            {
                this.Busy();

                IMaintenanceContract maintenanceContract = this._maintenanceContract.Channel;
                await Task.Run(() => checkedEquipmentAssets.ForEach(authority => maintenanceContract.MaintainEquipmentAsset(authority.Id)));
                await this.ReloadEquipmentAssets();

                this.Idle();
            }
        }
        #endregion

        #region 报废设备资产 —— async void ScrapEquipmentAssets()
        /// <summary>
        /// 报废设备资产
        /// </summary>
        public async void ScrapEquipmentAssets()
        {
            #region # 加载勾选

            EquipmentAssetInfo[] checkedEquipmentAssets = this.EquipmentAssets.Where(x => x.IsChecked == true).Select(x => x.Model).ToArray();
            if (!checkedEquipmentAssets.Any())
            {
                MessageBox.Show("请勾选要报废的设备资产！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            MessageBoxResult result = MessageBox.Show("确定要报废吗？", "警告", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            if (result == MessageBoxResult.Yes)
            {
                this.Busy();

                IMaintenanceContract maintenanceContract = this._maintenanceContract.Channel;
                await Task.Run(() => checkedEquipmentAssets.ForEach(authority => maintenanceContract.ScrapEquipmentAsset(authority.Id)));
                await this.ReloadEquipmentAssets();

                this.Idle();
            }
        }
        #endregion

        #region 打印设备资产 —— async void PrintEquipmentAssets()
        /// <summary>
        /// 打印设备资产
        /// </summary>
        public async void PrintEquipmentAssets()
        {
            #region # 验证

            if (this.EquipmentAssets.All(x => x.IsChecked != true))
            {
                MessageBox.Show("请勾选至少一条要打印的设备资产！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            IEnumerable<Wrap<EquipmentAssetInfo>> checkedWraps = this.EquipmentAssets.Where(x => x.IsChecked == true);

            this.Busy();

            PrintViewModel viewModel = ResolveMediator.Resolve<PrintViewModel>();
            viewModel.Load(checkedWraps.Select(x => x.Model));
            await this._windowManager.ShowDialogAsync(viewModel);

            this.Idle();
        }
        #endregion

        #region 导出设备资产 —— async void ExportEquipmentAssets()
        /// <summary>
        /// 导出设备资产
        /// </summary>
        public async void ExportEquipmentAssets()
        {
            string keywords = this.Keywords;
            Guid? equipmentId = this.SelectedEquipment?.Id;
            EquipmentStatus? equipmentStatus = this.SelectedEquipmentStatus;
            Guid? facilityId = this.SelectedFacility?.Id;
            PageModel<EquipmentAssetInfo> pageModel = await Task.Run(() => this._maintenanceContract.Channel.GetEquipmentAssetsByPage(keywords, equipmentId, equipmentStatus, facilityId, 1, int.MaxValue));

            EquipmentAssetEm[] equipmentAssetEms = pageModel.Datas.Select(x => x.ToExportView()).ToArray();
            if (!equipmentAssetEms.Any())
            {
                MessageBox.Show("导出数据为空，不能进行导出！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Filter = Constants.ExeclFileExtensionsFilter,
                FileName = $"设备台账_{DateTime.Now.ToString(Constants.ExportFileTimeFormat)}",
                AddExtension = true,
                RestoreDirectory = true
            };
            if (saveFileDialog.ShowDialog() == true)
            {
                string filePath = saveFileDialog.FileName;
                ExcelWriter.WriteFile(equipmentAssetEms, filePath);
            }
        }
        #endregion

        #region 全选 —— void CheckAll()
        /// <summary>
        /// 全选
        /// </summary>
        public void CheckAll()
        {
            this.EquipmentAssets.ForEach(x => x.IsChecked = true);
        }
        #endregion

        #region 取消全选 —— void UncheckAll()
        /// <summary>
        /// 取消全选
        /// </summary>
        public void UncheckAll()
        {
            this.EquipmentAssets.ForEach(x => x.IsChecked = false);
        }
        #endregion


        //Private

        #region 加载设备资产列表 —— async Task ReloadEquipmentAssets()
        /// <summary>
        /// 加载设备资产列表
        /// </summary>
        private async Task ReloadEquipmentAssets()
        {
            this.Busy();

            string keywords = this.Keywords;
            Guid? equipmentId = this.SelectedEquipment?.Id;
            EquipmentStatus? equipmentStatus = this.SelectedEquipmentStatus;
            Guid? facilityId = this.SelectedFacility?.Id;

            PageModel<EquipmentAssetInfo> pageModel = await Task.Run(() => this._maintenanceContract.Channel.GetEquipmentAssetsByPage(keywords, equipmentId, equipmentStatus, facilityId, this.PageIndex, this.PageSize));
            this.RowCount = pageModel.RowCount;
            this.PageCount = pageModel.PageCount;

            IEnumerable<Wrap<EquipmentAssetInfo>> wrapModels = pageModel.Datas.Select(x => x.Wrap());
            this.EquipmentAssets = new ObservableCollection<Wrap<EquipmentAssetInfo>>(wrapModels);

            this.Idle();
        }
        #endregion

        #endregion
    }
}
